import { ChartEdgeType, ChartNodeType } from '@/components/TaskRelationChart/dag.chart.dto'
import { HttpService } from '@/services/common/http/http.service'
import {
  ApiGetDagErrorResponseDto,
  ApiGetDagExecutionHistoryItem,
  ApiGetDagLogError,
  ApiGetDagLogSuccess,
  ApiGetDagSuccessResponseDto,
  ApiGetLatestTaskHistoryItem,
  ApiGetRegisterXxlJobListResponse,
  DagTaskInterface,
  DagTaskVertexInterface
} from './task.api.dto'
import { TaskChartDataDto } from './task.chart.dto'

export class TaskService {
  static delVertexByTaskId(
    dagName: string,
    taskId: number,
    taskName: string
  ): Promise<ApiGetRegisterXxlJobListResponse> {
    return HttpService.post<ApiGetRegisterXxlJobListResponse>(
      '/statistic/scheduler/delVertexByTaskId',
      {
        taskId,
        taskName,
        dagName
      }
    )
  }

  static getRegisterXxlJobList(): Promise<ApiGetRegisterXxlJobListResponse> {
    return HttpService.get<ApiGetRegisterXxlJobListResponse>(
      '/statistic/scheduler/getRegisterXxlJobList'
    )
  }

  static getDagLogFileByFilePath(
    filePath: string
  ): Promise<ApiGetDagLogSuccess | ApiGetDagLogError> {
    return HttpService.get<ApiGetDagLogSuccess | ApiGetDagLogError>(
      filePath,
      {},
      {
        headers: {
          'Content-Type': 'text/plain;charset=utf-8'
        }
      }
    )
  }

  static getDagLog(
    dagId: number,
    dagExecutionId: string,
    taskId: number
  ): Promise<ApiGetDagLogSuccess | ApiGetDagLogError> {
    return HttpService.get<ApiGetDagLogSuccess | ApiGetDagLogError>(
      '/statistic/logback/readDagLog',
      {
        dagExecutionId,
        dagId,
        taskId
      }
    )
  }

  static getLatestTaskHistory(dagExecutionId: string): Promise<Array<ApiGetLatestTaskHistoryItem>> {
    return HttpService.get<Array<ApiGetLatestTaskHistoryItem>>(
      '/statistic/scheduler/listLatestTaskHistory',
      {
        dagExecutionId
      }
    )
  }

  static getDagExecutionHistory(dagId: number): Promise<Array<ApiGetDagExecutionHistoryItem>> {
    return HttpService.get<Array<ApiGetDagExecutionHistoryItem>>(
      '/statistic/scheduler/listDagExecutionHistory',
      {
        dagId
      }
    ).then((response) => {
      if (response) {
        response.sort((a, b) => {
          return new Date(b.startTime).getTime() - new Date(a.startTime).getTime()
        })
      }
      return response
    })
  }

  static getDagInfo(
    dagName: string
  ): Promise<ApiGetDagSuccessResponseDto | ApiGetDagErrorResponseDto> {
    return HttpService.get<ApiGetDagSuccessResponseDto>('/statistic/scheduler/getDag', {
      dagName
    })
  }

  /**
   * 修改 task name
   */
  static updateTaskName(id: number, taskName: string) {
    return HttpService.post<ApiGetDagSuccessResponseDto>(`/statistic/scheduler/updateVertex`, {
      id,
      taskName
    })
  }

  static saveOperateStack() {
    return HttpService.post<ApiGetDagSuccessResponseDto>(`/statistic/scheduler/addVertex`, {
      dagName: 'test',
      taskName: 'StatisticOrderProfitTableXxlJob'
    })
  }

  static getAllDag() {}

  static transferDagInfo(response: ApiGetDagSuccessResponseDto): TaskChartDataDto {
    const edges: Array<ChartEdgeType> = []
    const nodes: Array<ChartNodeType> = []
    const { allDagTaskEdges, allDagTaskVertexes, firstDagTask, dagName } = response
    const dagId = allDagTaskVertexes[0].dagId || -1

    // 转换边数据
    const vertexMap: {
      [t: DagTaskVertexInterface['taskId']]: DagTaskVertexInterface & {
        col: number
        row: number
      }
    } = {}

    allDagTaskVertexes.forEach((item) => {
      vertexMap[item.taskId] = Object.assign(
        {
          col: 0,
          row: -1
        },
        item
      )
    })

    allDagTaskEdges.forEach((item) => {
      const edge: any = {}
      edge.source = vertexMap[item.taskId].taskName
      edge.target = vertexMap[item.nextTaskId].taskName
      edges.push(edge)
    })

    // 设置节点位置
    const yGap = 10
    const xGap = 20
    const yFloorList: Array<number> = []
    function setNodePosition(node: DagTaskInterface) {
      const vertex = vertexMap[node.taskId]
      const parentCol = vertex?.col || 0
      node.postTasks?.forEach((subNode) => {
        const subVertex = vertexMap[subNode.taskId]
        subVertex.col = parentCol + 1

        if (subVertex.row === -1) {
          if (yFloorList[subVertex.col] === undefined) {
            yFloorList[subVertex.col] = 0
          }
          subVertex.row = yFloorList[subVertex.col]++
        }

        setNodePosition(subNode)
      })
    }
    setNodePosition(firstDagTask)

    // 转换节点数据
    allDagTaskVertexes.forEach((item) => {
      const vertex = vertexMap[item.taskId]
      const node: ChartNodeType = {
        x: vertex.col * xGap,
        y: vertex.row * yGap,
        name: vertex.taskName,
        taskInfo: {
          ...vertex
        }
      }
      nodes.push(node)
    })

    return {
      edges,
      nodes,
      dagName,
      dagId
    }
  }

  static async getTaskChartData(
    datName: string
  ): Promise<TaskChartDataDto | ApiGetDagErrorResponseDto> {
    const dagInfo = await this.getDagInfo(datName)

    if (this.isErrorResponse(dagInfo)) {
      return dagInfo
    }

    return this.transferDagInfo(dagInfo)
  }

  static isErrorResponse(
    response: ApiGetDagSuccessResponseDto | ApiGetDagErrorResponseDto
  ): response is ApiGetDagErrorResponseDto {
    return 'message' in response || 'msg' in response
  }

  static isCorrectData(
    response: TaskChartDataDto | ApiGetDagErrorResponseDto
  ): response is TaskChartDataDto {
    return 'nodes' in response && 'edges' in response && 'dagName' in response
  }
}
